package lwk.pool;

import java.util.concurrent.*;

/**
 * @author:lwk
 * @create: 2022-08-18 20:38
 * @Description: 线程池
 *　　池化技术：
 *     　　01：程序的运行，本质 ：占用系统的资源！ 优化资源的使用！  =>池化技术
 *     　　02：线程池、连接池、内存池、对象池///......创建、销毁。 十分浪费资源
 *     　　03：池化技术：事先准备好一些资源，有人要用，就来我这里拿，用完之后还给我。
 * 　　线程池的好处：
 *     　　01：降低资源的消耗
 *     　　02：提高响应的速度
 *     　　03：方便管理
 *    　　（重点）线程复用、可以控制最大并发数、管理线程
 *
 *    三大方法，源码可知均基于ThreadPoolExecutor
 *         //单个线程
 *         ExecutorService threadPool = Executors.newSingleThreadExecutor();
 *         // 创建一个固定大小的线程池
 *         ExecutorService threadPool2 = Executors.newFixedThreadPool(5);
 *         // 可伸缩的线程池
 *         ExecutorService threadPool3 = Executors.newCachedThreadPool();
 *
 *    七大参数（银行办理业务举例：一共5个窗口，常开的有2个，椅子有3个，如果有两个人正在窗口办理业务，
 *              还可以正常进3个人坐在椅子上，如果椅子坐满了，还在进人，就会临时加开窗口，加开的窗口会在椅子没有坐满后一段时间关闭。如果加开窗口之后，椅子坐满后还在进人，就要启动拒绝策略）
 *         public ThreadPoolExecutor(int corePoolSize,                  // 核心线程池大小                        通常在服务中的窗口（2）
 *                               int maximumPoolSize,                   // 最大核心线程池大小                    最多有多少窗口（5）
 *                               long keepAliveTime,                    // 超时了没有人调用就会释放                没人之后多久关掉不通常打开的窗口（5-2=3）
 *                               TimeUnit unit,                         // 超时单位                             超时的单位
 *                               BlockingQueue<Runnable> workQueue,     // 阻塞队列                             银行等候区域的椅子（3）
 *                               ThreadFactory threadFactory,           // 线程工厂，创建线程使用，一般不动
 *                               RejectedExecutionHandler handler)      // 拒绝策略
 *
 *    四种拒绝策略
 *         AbortPolicy（默认）：直接抛出RejectedExecutionException异常阻止系统正常运行。
 *         DiscardPolicy：丢弃无法处理的任务，不会抛出异常。（如果允许任务丢失，这是最好的一种策略）
 *         DiscardOldestPolicy：抛弃队列中等待最久的任务，重新提交当前任务。
 *         CallerRunsPolicy（调用者运行）：由调用线程（提交任务的线程）处理该任务
 *         ————————————————
 *         版权声明：本文为CSDN博主「Mitsuha三葉」的原创文章，遵循CC 4.0 BY-SA版权协议，转载请附上原文出处链接及本声明。
 *         原文链接：<a href="https://blog.csdn.net/qq_42804736/article/details/114657043">三大方法，七大参数，四种拒绝策略</a>
 */
public class Demo01 {
    public static void main(String[] args) {

        /**
         * 七大参数（银行办理业务举例：一共5个窗口，常开的有2个，椅子有3个，如果有两个人正在窗口办理业务，
         *           还可以正常进3个人坐在椅子上，如果椅子坐满了，还在进人，就会临时加开窗口，加开的窗口在空闲一段时间后关闭。如果加开窗口之后，椅子坐满后还在进人，就要启动拒绝策略）
         *      public ThreadPoolExecutor(int corePoolSize,                  // 核心线程池大小                        通常在服务中的窗口（2）
         *                            int maximumPoolSize,                   // 最大核心线程池大小                    最多有多少窗口（5）
         *                            long keepAliveTime,                    // 超时了没有人调用就会释放                没人之后多久关掉不通常打开的窗口（5-2=3）
         *                            TimeUnit unit,                         // 超时单位                             超时的单位
         *                            BlockingQueue<Runnable> workQueue,     // 阻塞队列                             银行等候区域的椅子（3）
         *                            ThreadFactory threadFactory,           // 线程工厂，创建线程使用，一般不动
         *                            RejectedExecutionHandler handler)      // 拒绝策略
         *
         *                            最大线程到底该怎么定义：
         *                              1、CPU密集型  几核CPU就是几，可以保持CPU效率最高 Runtime.getRuntime().availableProcessors()
         *                              2、IO 密集型    判断程序中十分耗IO的线程数，只要大于该线程数就行，一般两倍IO任务的两倍
         */

        ExecutorService bankPool = new ThreadPoolExecutor(2,5,3, TimeUnit.SECONDS,new LinkedBlockingQueue<>(3),Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());

        // 超过最大承载 maximumPoolSize + workQueue = 5 + 3 = 8，超过8可能会抛出异常
        // java.util.concurrent.RejectedExecutionException
        try {
            for (int i = 1; i <= 9; i++) {
                bankPool.execute(()-> System.out.println(Thread.currentThread().getName()));
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            bankPool.shutdown();
        }

        //单个线程
        ExecutorService threadPool = Executors.newSingleThreadExecutor();


        try {
            for (int i = 0; i < 10; i++) {
                threadPool.execute(()-> System.out.println(Thread.currentThread().getName() + "---OK"));
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            threadPool.shutdown();
        }

        // 创建一个固定大小的线程池
        ExecutorService threadPool2 = Executors.newFixedThreadPool(5);
        try {
            for (int i = 0; i < 10; i++) {
                threadPool2.execute(()-> System.out.println(Thread.currentThread().getName() + "---OK"));
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            threadPool2.shutdown();
        }

        // 可伸缩的线程池
        ExecutorService threadPool3 = Executors.newCachedThreadPool();
        try {
            for (int i = 0; i < 10; i++) {
                threadPool3.execute(()-> System.out.println(Thread.currentThread().getName() + "---OK"));
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            threadPool3.shutdown();
        }
    }
}
